package bbs.service.impl;

import java.io.File;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import bbs.entity.config.AppConfig;
import bbs.entity.constants.Constants;
import bbs.entity.dto.FileUploadDto;
import bbs.entity.dto.SysSetting4AuditDto;
import bbs.entity.enums.*;
import bbs.entity.po.ForumArticleAttachment;
import bbs.entity.po.ForumBoard;
import bbs.entity.po.UserMessage;
import bbs.entity.query.ForumArticleAttachmentQuery;
import bbs.exception.BusinessException;
import bbs.mappers.ForumArticleAttachmentMapper;
import bbs.service.ForumBoardService;
import bbs.service.UserInfoService;
import bbs.service.UserMessageService;
import bbs.utils.FileUtil;
import bbs.utils.ImageUtils;
import bbs.utils.SysCacheUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import bbs.entity.query.ForumArticleQuery;
import bbs.entity.po.ForumArticle;
import bbs.entity.vo.PaginationResultVO;
import bbs.entity.query.SimplePage;
import bbs.mappers.ForumArticleMapper;
import bbs.service.ForumArticleService;
import bbs.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


/**
 * 文章信息 业务接口实现
 */
@Service("forumArticleService")
public class ForumArticleServiceImpl implements ForumArticleService {

	@Resource
	private ForumArticleMapper<ForumArticle, ForumArticleQuery> forumArticleMapper;

	@Resource
	private ForumBoardService forumBoardService;

	@Resource
	private FileUtil fileUtil;

	@Resource
	private ForumArticleAttachmentMapper<ForumArticleAttachment, ForumArticleAttachmentQuery> forumArticleAttachmentMapper;

	@Resource
	private UserInfoService userInfoService;

	@Resource
	private ImageUtils imageUtils;

	@Resource
	private AppConfig appConfig;

	@Lazy
	@Resource
	private ForumArticleService forumArticleService;

	@Resource
	private UserMessageService userMessageService;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<ForumArticle> findListByParam(ForumArticleQuery param) {
		return this.forumArticleMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(ForumArticleQuery param) {
		return this.forumArticleMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<ForumArticle> findListByPage(ForumArticleQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE5.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<ForumArticle> list = this.findListByParam(param);
		PaginationResultVO<ForumArticle> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(ForumArticle bean) {
		return this.forumArticleMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<ForumArticle> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.forumArticleMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<ForumArticle> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.forumArticleMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(ForumArticle bean, ForumArticleQuery param) {
		StringTools.checkParam(param);
		return this.forumArticleMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(ForumArticleQuery param) {
		StringTools.checkParam(param);
		return this.forumArticleMapper.deleteByParam(param);
	}

	/**
	 * 根据ArticleId获取对象
	 */
	@Override
	public ForumArticle getForumArticleByArticleId(String articleId) {
		return this.forumArticleMapper.selectByArticleId(articleId);
	}

	/**
	 * 根据ArticleId修改
	 */
	@Override
	public Integer updateForumArticleByArticleId(ForumArticle bean, String articleId) {
		return this.forumArticleMapper.updateByArticleId(bean, articleId);
	}

	/**
	 * 根据ArticleId删除
	 */
	@Override
	public Integer deleteForumArticleByArticleId(String articleId) {
		return this.forumArticleMapper.deleteByArticleId(articleId);
	}


	/**
	 * 文章阅读量
	 * @param articleId
	 * @return
	 */
    @Override
    public ForumArticle readArticle(String articleId) {
        ForumArticle forumArticle = this.forumArticleMapper.selectByArticleId(articleId);
		if (forumArticle == null) throw new BusinessException(ResponseCodeEnum.CODE_404);

		if (ArticleStatusEnum.AUDIT.getStatus().equals(forumArticle.getStatus())){
			forumArticleMapper.updateArticleCount(articleId, Constants.ONE,UpdateArticleCountTypeEnum.READ_COUNT.getType());
		}

		return forumArticle;
    }


    @Override
    public void postArticle(Boolean isAdmin, ForumArticle forumArticle, ForumArticleAttachment forumArticleAttachment, MultipartFile cover, MultipartFile attachment)
	{
		resetBoardInfo(isAdmin, forumArticle);

		Date curDate = new Date();
		String articleId = StringTools.getRandomString(Constants.LENGTH_15);
		forumArticle.setArticleId(articleId);
		forumArticle.setPostTime(curDate);
		forumArticle.setLastUpdateTime(curDate);

		if (cover != null) {
			FileUploadDto fileUploadDto = fileUtil.uploadFile2Local(cover, Constants.FILE_FOLDER_IMAGE, FileUploadTypeEnum.ARTICLE_COVER);
			forumArticle.setCover(fileUploadDto.getLocalPath());
		}

		if (attachment != null) {
			uploadAttachment(forumArticle, forumArticleAttachment, attachment, false);
			forumArticle.setAttachmentType(ArticleAttachmentTypeEnum.HAVE_ATTACHMENT.getType());
		} else {
			forumArticle.setAttachmentType(ArticleAttachmentTypeEnum.NO_ATTACHMENT.getType());
		}
//		判断帖子是否需要审核
		if (isAdmin) {
			forumArticle.setStatus(ArticleStatusEnum.AUDIT.getStatus());
		} else {
			SysSetting4AuditDto auditDto = SysCacheUtils.getSysSetting().getAuditSetting();
			forumArticle.setStatus(auditDto.getPostAudit() ? ArticleStatusEnum.NO_AUDIT.getStatus() : ArticleStatusEnum.AUDIT.getStatus());
		}

//		替换图片
		String content = forumArticle.getContent();
		if (!StringTools.isEmpty(content)) {
			String month = imageUtils.resetImageHtml(content);
			String replacement = "/" + month + "/";
			content = content.replace(Constants.FILE_FOLDER_TEMP, replacement);
			forumArticle.setContent(content);
			String markdownContent = forumArticle.getMarkdownContent();
			if (!StringTools.isEmpty(markdownContent)) {
				markdownContent = markdownContent.replace(Constants.FILE_FOLDER_TEMP, replacement);
				forumArticle.setMarkdownContent(markdownContent);
			}
		}
		forumArticleMapper.insert(forumArticle);

//		用户发帖后给予积分
		Integer postIntegral = SysCacheUtils.getSysSetting().getPostSetting().getPostIntegral();
		if (postIntegral > 0 && ArticleStatusEnum.AUDIT.equals(forumArticle.getStatus()))
			userInfoService.updateUserInternal(forumArticle.getUserId(), UserIntegralOperTypeEnum.POST_ARTICLE, UserIntegralChangeTypeEnum.ADD.getChangeType(), postIntegral);
    }

	/**
	 * 修改帖子
	 * @param isAdmin
	 * @param article
	 * @param articleAttachment
	 * @param cover
	 * @param attachment
	 */
	@Override
	public void updateArticle(Boolean isAdmin, ForumArticle article, ForumArticleAttachment articleAttachment, MultipartFile cover, MultipartFile attachment) {
		ForumArticle dbInfo = forumArticleMapper.selectByArticleId(article.getArticleId());
		if (!isAdmin && dbInfo.getUserId().equals(article.getArticleId())) {
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		article.setLastUpdateTime(new Date());
		resetBoardInfo(isAdmin, article);
		if (cover != null) {
			FileUploadDto fileUploadDto = fileUtil.uploadFile2Local(cover, Constants.FILE_FOLDER_IMAGE, FileUploadTypeEnum.ARTICLE_COVER);
			article.setCover(fileUploadDto.getLocalPath());
		}
		if (attachment != null) {
			uploadAttachment(article, articleAttachment, attachment, true);
			article.setAttachmentType(ArticleAttachmentTypeEnum.HAVE_ATTACHMENT.getType());
		}

//		修改附件
		ForumArticleAttachment dbAttachment = null;
		ForumArticleAttachmentQuery articleAttachmentQuery = new ForumArticleAttachmentQuery();
		articleAttachmentQuery.setArticleId(article.getArticleId());
		List<ForumArticleAttachment> articleAttachmentList = forumArticleAttachmentMapper.selectList(articleAttachmentQuery);
		if (!articleAttachmentList.isEmpty()) {
			dbAttachment = articleAttachmentList.get(0);
		}

		if (dbAttachment != null) {
			if (article.getAttachmentType() == Constants.ZERO) {
				new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_ATTACHMENT + dbAttachment.getFilePath()).delete();
				forumArticleAttachmentMapper.deleteByFileId(dbAttachment.getFileId());
			} else {
				if (!dbAttachment.getIntegral().equals(articleAttachment.getIntegral())) {
					ForumArticleAttachment integralUpdate = new ForumArticleAttachment();
					integralUpdate.setIntegral(articleAttachment.getIntegral());
					forumArticleAttachmentMapper.updateByFileId(integralUpdate, dbAttachment.getFileId());
				}
			}
		}

//		判断帖子是否需要审核
		if (isAdmin) {
			article.setStatus(ArticleStatusEnum.AUDIT.getStatus());
		} else {
			SysSetting4AuditDto auditDto = SysCacheUtils.getSysSetting().getAuditSetting();
			article.setStatus(auditDto.getPostAudit() ? ArticleStatusEnum.NO_AUDIT.getStatus() : ArticleStatusEnum.AUDIT.getStatus());
		}
//		替换图片
		String content = article.getContent();
		if (!StringTools.isEmpty(content)) {
			String month = imageUtils.resetImageHtml(content);
			String replacement = "/" + month + "/";
			content = content.replace(Constants.FILE_FOLDER_TEMP, replacement);
			article.setContent(content);
			String markdownContent = article.getMarkdownContent();
			if (!StringTools.isEmpty(markdownContent)) {
				markdownContent = markdownContent.replace(Constants.FILE_FOLDER_TEMP, replacement);
				article.setMarkdownContent(markdownContent);
			}
		}
		forumArticleMapper.updateByArticleId(article, article.getArticleId());
	}

	@Override
	public void delArticle(String articleIds) {
		String[] articleArray = articleIds.split(",");
		for (String articleId : articleArray) {
			forumArticleService.delArticleSingle(articleId);
		}
	}

	@Transactional(rollbackFor = Exception.class)
	public void delArticleSingle(String articleId) {
		ForumArticle article = getForumArticleByArticleId(articleId);
		if (article == null || ArticleStatusEnum.DEL.getStatus().equals(article.getStatus())) return;

		ForumArticle updateInfo = new ForumArticle();
		updateInfo.setStatus(ArticleStatusEnum.DEL.getStatus());
		forumArticleMapper.updateByArticleId(updateInfo, articleId);

		Integer integral = SysCacheUtils.getSysSetting().getPostSetting().getPostIntegral();
		if (integral > 0 && ArticleStatusEnum.AUDIT.getStatus().equals(article.getStatus()))
			userInfoService.updateUserInternal(article.getUserId(), UserIntegralOperTypeEnum.DEL_ARTICLE, UserIntegralChangeTypeEnum.REDUCE.getChangeType(), integral);

		UserMessage userMessage = new UserMessage();
		userMessage.setReceivedUserId(article.getUserId());
		userMessage.setMessageType(MessageTypeEnum.SYS.getType());
		userMessage.setCreateTime(new Date());
		userMessage.setStatus(MessageStatusEnum.UNREAD.getStatus());
		userMessage.setMessageContent("讨论帖《" + article.getTitle() + "》已被删除");
		userMessageService.add(userMessage);
	}

	@Override
	public void UpdateBoard(String articleId, Integer pBoardId, Integer BoardId) {
		ForumArticle forumArticle = new ForumArticle();
		forumArticle.setpBoardId(pBoardId);
		forumArticle.setBoardId(BoardId);
		resetBoardInfo(true, forumArticle);
		forumArticleMapper.updateByArticleId(forumArticle, articleId);
	}

	@Override
	public void auditArticle(String articleIds) {
		String[] articleArray = articleIds.split(",");
		for (String articleId : articleArray) {
			forumArticleService.auditArticleSignle(articleId);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void auditArticleSignle(String articleId) {
		ForumArticle article = getForumArticleByArticleId(articleId);
		if (article == null || !ArticleStatusEnum.NO_AUDIT.getStatus().equals(article.getStatus())) return;

		ForumArticle updateInfo = new ForumArticle();
		updateInfo.setStatus(ArticleStatusEnum.AUDIT.getStatus());
		forumArticleMapper.updateByArticleId(updateInfo, articleId);

		Integer integral = SysCacheUtils.getSysSetting().getPostSetting().getPostIntegral();
		if (integral > 0 && ArticleStatusEnum.AUDIT.getStatus().equals(article.getStatus()))
			userInfoService.updateUserInternal(article.getUserId(), UserIntegralOperTypeEnum.POST_ARTICLE, UserIntegralChangeTypeEnum.ADD.getChangeType(), integral);
	}

	/**
	 * 修改版块信息
	 * @param isAdmin
	 * @param forumArticle
	 */
	private void resetBoardInfo(Boolean isAdmin, ForumArticle forumArticle) {
		ForumBoard pBorad = forumBoardService.getForumBoardByBoardId(forumArticle.getpBoardId());
		if (pBorad == null || !pBorad.getPostType().equals(Constants.ONE) && !isAdmin) {
			throw new BusinessException(Constants.BOARD_NOT_EXISTS);
		}
		forumArticle.setpBoardName(pBorad.getBoardName());

		if (forumArticle.getBoardId() != null && forumArticle.getBoardId() != 0) {
			ForumBoard board = forumBoardService.getForumBoardByBoardId(forumArticle.getBoardId());
			if (board == null || !board.getPostType().equals(Constants.ONE) && !isAdmin) {
				throw new BusinessException(Constants.BOARD_NOT_EXISTS);
			}
			forumArticle.setBoardName(board.getBoardName());
		}else {
			forumArticle.setBoardId(Constants.ZERO);
			forumArticle.setBoardName("");
		}
	}

	private void uploadAttachment(ForumArticle article, ForumArticleAttachment articleAttachment, MultipartFile file, Boolean isUpdate)
	{
		Integer allowSize = SysCacheUtils.getSysSetting().getPostSetting().getAttachmentSize();
		if ( file.getSize() >= allowSize *  1024 * 1024) {
			throw new BusinessException("附件最大容量为" + allowSize + "MB");
		}
//		修改附件
		ForumArticleAttachment dbinfo = null;
		if(isUpdate) {
			ForumArticleAttachmentQuery articleAttachmentQuery = new ForumArticleAttachmentQuery();
			articleAttachmentQuery.setArticleId(article.getArticleId());
			List<ForumArticleAttachment> articleAttachmentList = forumArticleAttachmentMapper.selectList(articleAttachmentQuery);
			if (!articleAttachmentList.isEmpty()) {
				dbinfo = articleAttachmentList.get(0);
				new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_ATTACHMENT + dbinfo.getFilePath()).delete();
			}
		}
		FileUploadDto fileUploadDto = fileUtil.uploadFile2Local(file, Constants.FILE_FOLDER_ATTACHMENT, FileUploadTypeEnum.ARTICLE_ATTACHMENT);


		if (dbinfo == null) {
			articleAttachment.setArticleId(article.getArticleId());
			articleAttachment.setFileId(StringTools.getRandomNumber(Constants.LENGTH_15));
			articleAttachment.setFileName(fileUploadDto.getOriginalFileName());
			articleAttachment.setFilePath(fileUploadDto.getLocalPath());
			articleAttachment.setFileSize(file.getSize());
			articleAttachment.setDownloadCount(Constants.ZERO);
			articleAttachment.setFileType(AttachmentFileTypeEnum.ZIP.getType());
			articleAttachment.setUserId(article.getUserId());
			forumArticleAttachmentMapper.insert(articleAttachment);
		} else {
			ForumArticleAttachment updateInfo = new ForumArticleAttachment();
			updateInfo.setFileName(fileUploadDto.getOriginalFileName());
			updateInfo.setFilePath(fileUploadDto.getLocalPath());
			updateInfo.setFileSize(file.getSize());
			forumArticleAttachmentMapper.updateByFileId(updateInfo, dbinfo.getFileId());
		}
	}
}